import { AnimationBuilder } from '@angular/animations';
import {
  Directive,
  ElementRef,
  Injector,
  Input,
  OnChanges,
  OnInit,
  SimpleChanges,
  ViewContainerRef,
} from '@angular/core';
import { InputBoolean, InputNumber } from '../core/api';
import { BadgeComponent } from './badge.component';

@Directive({
  selector: '[lv-badge], [lvBadge]',
  exportAs: 'lvBadge',
  host: {
    '[class.lv-badge-wrapper]': 'true',
  },
})
export class BadgeDirective implements OnInit, OnChanges {
  @Input('lv-badge') @InputNumber() lvValue = 0;

  @Input('lvBadgeDot') @InputBoolean() lvDot = false;

  @Input('lvBadgeTextColor') lvTextColor: string = '';

  @Input('lvBadgeMaxValue') @InputNumber() lvMaxValue = 999;

  @Input('lvBadgeVisible') @InputBoolean() lvVisible = true;

  @Input('lvBadgeShowZero') @InputBoolean() lvShowZero = false;

  @Input('lvBadgeBackgroundColor') lvBackgroundColor: string = '';

  public badge: BadgeComponent;
  protected properties = [
    'lvValue',
    'lvMaxValue',
    'lvVisible',
    'lvDot',
    'lvShowZero',
    'lvTextColor',
    'lvBackgroundColor',
  ];

  constructor(
    private el: ElementRef,
    protected ViewContainer: ViewContainerRef,
    private injector: Injector,
  ) {}

  ngOnInit(): void {
    this.createComponent();
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (this.badge) {
      this.lvValue = Math.max(0, this.lvValue);
      this.lvMaxValue = Math.max(0, this.lvMaxValue);

      this.properties.forEach((property): void => {
        this.updateComponentProperties(property, this[property]);
      });

      if (changes.lvValue) {
        this.badge.getValueArray();
      }
      if (changes.lvMaxValue) {
        this.badge.getMaxValueArray();
      }

      this.badge.cdr.markForCheck();
    }
  }

  private updateComponentProperties(key, value): void {
    if (value !== null || value !== undefined) {
      this.badge[key] = value;
    }
  }

  private createComponent(): void {
    this.injector.get(AnimationBuilder);
    const componentRef = this.ViewContainer.createComponent(BadgeComponent, { injector: this.injector });
    this.badge = componentRef.instance;
    this.el.nativeElement.appendChild(this.badge.el.nativeElement);

    this.init();
  }

  private init(): void {
    this.lvValue = Math.max(0, this.lvValue);
    this.lvMaxValue = Math.max(0, this.lvMaxValue);

    this.properties.forEach((property): void => {
      this.updateComponentProperties(property, this[property]);
    });

    this.badge.getValueArray();
    this.badge.getMaxValueArray();
  }
}
